// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.

namespace Microsoft.Samples.Commerce.Order.CommerceEntities
{
    using Microsoft.Commerce.Contracts;

    /// <summary>
    /// Payment method is a configured payment type.
    /// </summary>
    /// <remarks>
    /// The commerce system (site) can have one or more configured payment types such as credit cards,
    /// gift certificates, cash cards etc. This class represents a payment type that the system accepts.
    /// It also allows the configured payment types to be enumerated and displayed to the user in the UI.
    /// </remarks>
    public class PaymentMethod : ICommerceEntity
    {
        /// <summary>
        /// defines the model name for this commerce entity
        /// </summary>
        public const string ModelNameDefinition = "PaymentMethod";

        /// <summary>
        /// The commerce entity.
        /// </summary>
        private CommerceEntity commerceEntity;

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="PaymentMethod"/> class.
        /// </summary>
        public PaymentMethod()
        {
            this.commerceEntity = new CommerceEntity(PaymentMethod.ModelNameDefinition);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PaymentMethod"/> class.
        /// </summary>
        /// <param name="commerceEntity">The commerce entity.</param>
        public PaymentMethod(CommerceEntity commerceEntity)
        {
            this.commerceEntity = commerceEntity;
        }

        #endregion

        #region ICommerceEntity Members

        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id of the entity.</value>
        public string Id
        {
            get { return this.commerceEntity.Id; }
            set { this.commerceEntity.Id = value; }
        }

        /// <summary>
        /// Gets or sets the type name of this object instance
        /// <remarks>Required so that the Builders can convert to the Multi-channel Commerce Foundation CommerceEntity base type</remarks>
        /// </summary>
        /// <value></value>
        public string ModelName
        {
            get { return this.commerceEntity.ModelName; }
            set { this.commerceEntity.ModelName = value; }
        }

        /// <summary>
        /// Gets or sets this objects collection of Properties and their corresponding values
        /// </summary>
        /// <value></value>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Collection setting is required")]
        public CommercePropertyCollection Properties
        {
            get { return this.commerceEntity.Properties; }
            set { this.commerceEntity.Properties = value; }
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the display name of the payment method.
        /// </summary>
        /// <value>The display name.</value>
        /// <remarks>This is the name that is used in the UI to help to identify the payment method for
        /// the user: "Visa, "MasterCard" etc.</remarks>
        public string DisplayName
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.DisplayName) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.DisplayName, value); }
        }

        /// <summary>
        /// Gets or sets the payment method description. This is an optional detailed description of the payment method.
        /// </summary>
        /// <value>The description.</value>
        public string Description
        {
            get { return this.commerceEntity.GetPropertyValue(PropertyName.Description) as string; }
            set { this.commerceEntity.SetPropertyValue(PropertyName.Description, value); }
        }

        /// <summary>
        /// Gets or sets the PaymentType enumeration value.
        /// </summary>
        /// <value>The type of the payment.</value>
        public int? PaymentType
        {
            get { return (int?)this.commerceEntity.GetPropertyValue(PropertyName.PaymentType); }
            set { this.commerceEntity.SetPropertyValue(PropertyName.PaymentType, value ?? null); }
        }

        #endregion

        #region Implicit operators
        /// <summary>
        /// Toes the user profile.
        /// </summary>
        /// <param name="commerceEntity">The commerce entity.</param>
        /// <returns></returns>
        public static implicit operator PaymentMethod(CommerceEntity commerceEntity)
        {
            System.Diagnostics.Debug.Assert(PaymentMethod.ModelNameDefinition.Equals(commerceEntity.ModelName), "Unexpected model name");
            return new PaymentMethod(commerceEntity);
        }
        #endregion

        /// <summary>
        /// Required so that the Builders can convert to the Multi-channel Commerce Foundation CommerceEntity base type using <see cref="ModelName"/>
        /// </summary>
        /// <returns>This instances base type</returns>
        public CommerceEntity ToCommerceEntity()
        {
            return this.commerceEntity;
        }

        #region Property key names

        /// <summary>
        /// Names of the properties exposed by this commerce entity.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "Needed for external access"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1053:StaticHolderTypesShouldNotHaveConstructors", Justification = "Cannot make it private as it cannot be derived from")]
        public class PropertyName : CommerceEntity.PropertyName
        {
            #region Constants

            /// <summary>
            /// The name of the DisplayName property for a PaymentMethod.
            /// </summary>
            public const string DisplayName = "DisplayName";

            /// <summary>
            /// The name of the Description property for a PaymentMethod.
            /// </summary>
            public const string Description = "Description";

            /// <summary>
            /// The name of the PaymentType property for a PaymentMethod.
            /// </summary>
            public const string PaymentType = "PaymentType";

            #endregion
        }

        #endregion
    }
}
